﻿using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

namespace DevExpress.Xpf.DemoBase {
    public static class IDataErrorInfoHelper {
        public static string GetErrorText(object owner, string propertyName) {
            string[] path = propertyName.Split('.');
            if(path.Length > 1)
                return GetErrorText(owner, path);
            PropertyInfo propertyInfo = owner.GetType().GetProperty(propertyName);
            if (propertyInfo == null) return null;
            object propertyValue = propertyInfo.GetValue(owner, null);
            ValidationContext validationContext = new ValidationContext(owner, null, null) { MemberName = propertyName };
            string[] errors = propertyInfo
                .GetCustomAttributes(false)
                .OfType<ValidationAttribute>()
                .Select(x => x.GetValidationResult(propertyValue, validationContext))
                .Where(x => x != null)
                .Select(x => x.ErrorMessage)
                .Where(x => !string.IsNullOrEmpty(x))
                .ToArray();
            return string.Join(" ", errors);
        }
        public static string GetErrorText(object owner, string[] path) {
            string nestedPropertyName = string.Join(".", path.Skip(1));
            string propertyName = path[0];
            PropertyInfo propertyInfo = owner.GetType().GetProperty(propertyName);
            if(propertyInfo == null)
                return null;
            object propertyValue = propertyInfo.GetValue(owner, null);
            IDataErrorInfo nestedDataErrorInfo = propertyValue as IDataErrorInfo;
            return nestedDataErrorInfo == null ? string.Empty : nestedDataErrorInfo[nestedPropertyName];
        }
    }
    public static class DataAnnotationHelper {
        public static bool IsRequired<TEntity>(string propertyName) {
            return IsSet<RequiredAttribute>(typeof(TEntity), propertyName);
        }
        public static bool IsPhone<TEntity>(string propertyName) {
            return IsSet<PhoneAttribute>(typeof(TEntity), propertyName);
        }
        public static bool IsEmail<TEntity>(string propertyName) {
            return IsSet<EmailAddressAttribute>(typeof(TEntity), propertyName);
        }
        public static bool IsZipcode<TEntity>(string propertyName) {
            return IsSet<ZipCodeAttribute>(typeof(TEntity), propertyName);
        }
        public static bool IsSet<TAttribute>(System.Type type, string propertyName) where TAttribute : ValidationAttribute {
            string[] path = propertyName.Split('.');
            if(path.Length > 1) {
                PropertyInfo nestedPropertyInfo = type.GetProperty(path[0]);
                if(nestedPropertyInfo == null)
                    return false;
                return IsSet<TAttribute>(nestedPropertyInfo.PropertyType, string.Join(".", path.Skip(1)));
            }
            PropertyInfo propertyInfo = type.GetProperty(propertyName);
            if(propertyInfo == null)
                return false;
            return propertyInfo.GetCustomAttributes(false).OfType<TAttribute>().Any();
        }
    }
}
